package com.yuandengta.yomall.auth.service.impl;

import com.fasterxml.jackson.core.type.TypeReference;
import com.yuandengta.common.constant.AuthConstant;
import com.yuandengta.common.exception.BizCode;
import com.yuandengta.common.exception.RRException;
import com.yuandengta.common.utils.R;
import com.yuandengta.yomall.auth.exception.AuthBizException;
import com.yuandengta.yomall.auth.feign.MemberFeignService;
import com.yuandengta.yomall.auth.feign.ThirdPartyFeignService;
import com.yuandengta.yomall.auth.service.SmsService;
import com.yuandengta.yomall.auth.vo.UserRegisterVO;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.security.SecureRandom;
import java.util.Random;
import java.util.concurrent.TimeUnit;

/**
 * 短信服务接口 {@link SmsServcieImpl}
 *
 * @author Kevin
 * @email: 178676392@qq.com
 */
@Slf4j
@Service
public class SmsServcieImpl implements SmsService {

    @Autowired
    private ThirdPartyFeignService thirdPartyFeignService;

    @Autowired
    private StringRedisTemplate redisTemplate;

    /**
     * 发送短信验证码
     * @param mobile 手机号码
     */
    @Override
    public void sendCode(String mobile) {
        // 从缓存中获取验证码
        String redisCode = redisTemplate.opsForValue().get(AuthConstant.SMS_CODE_CACHE_PREFIX + mobile);
        if (!StringUtils.isEmpty(redisCode)) {
            long codeTime = Long.parseLong(redisCode.split("_")[1]);
            long currTime = System.currentTimeMillis();
            if (currTime - codeTime < 60000) {
                // 60 秒内不能再次发送验证码
                throw new AuthBizException(BizCode.SMS_CODE_EXCEPTION.getMessage(), BizCode.SMS_CODE_EXCEPTION.getCode());
            }
        }

        String code = getCheckCode();
        // 验证码校验，将验证码放入到 redis 中
        redisTemplate.opsForValue().set(AuthConstant.SMS_CODE_CACHE_PREFIX + mobile,
                code + "_" + System.currentTimeMillis(), 10, TimeUnit.MINUTES);

        // 发送短信验证码
        R r = thirdPartyFeignService.sendCode(mobile, code);
        if (r.getCode() != 0) {
            log.error("调用远程服务 yomall-third-party 发送短信验证码失败");
        }
    }

    /**
     * 校验验证码
     * @param mobile 手机号码
     * @param code 验证码
     * @return
     */
    @Override
    public boolean checkCode(String mobile, String code) {
        String redisCode = redisTemplate.opsForValue().get(AuthConstant.SMS_CODE_CACHE_PREFIX + mobile);
        if (StringUtils.isEmpty(redisCode)) {
            return false;
        } else {
            if (code.equals(redisCode.split("_")[0])) {
                // 删除验证码, 令牌机制
                redisTemplate.delete(AuthConstant.SMS_CODE_CACHE_PREFIX + mobile);
                return true;
            } else {
                return false;
            }
        }
    }

    /**
     * 生成随机六位数字验证码
     * @return
     */
    private String getCheckCode () {
        char[] nonceChars = new char[6];
        for (int i = 0; i < nonceChars.length; ++i) {
            nonceChars[i] = SYMBOLS.charAt(RANDOM.nextInt(SYMBOLS.length()));
        }

        return new String(nonceChars);
    }

    private static final String SYMBOLS = "0123456789";
    //    private static final String SYMBOLS = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
    private static final Random RANDOM = new SecureRandom();
}
